package com.atguigu.gmall.mq.listener;

import com.atguigu.gmall.mq.config.DeadLetterMqConfig;
import com.atguigu.gmall.mq.config.DelayedMqConfig;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;

/**
 * @author 李旭
 * @date 2021/12/1 11:42
 * @Description:
 */
@SuppressWarnings("all")
@Component
public class ReceiverMessage {


    /**
     * 基于插件的 消息消费
     * @param msg
     * @param message
     * @param channel
     */
    @RabbitListener(queues = {DelayedMqConfig.queue_delay_1})
    public void receiverDelayedMessage(String msg, Message message, Channel channel) {
        try {
            System.out.println("接收到的消息：" + msg + ":时间是:" + new Date());
            //处理。。。

            //手动应答
            //参数1：消息的标识
            //参数2：是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //e.printStackTrace();
            //重新使用监听器获取队列中消息  重新接收一次
            //判断当前消息是否已经投递过了
            //                 如果已经投递过了 就证明上一次投递失败了 不能再投递一次
            //                 如果没有投递过、这是新消息  可以再投递一次
            //Boolean redelivered :
            //   是否投递过  true:已经投递过了本次第二次投递   false:没有投递过 本次是第一次投递
            if (message.getMessageProperties().isRedelivered()) {
                //true:已经投递过了本次第二次投递
                System.out.println("本次是第二次投递了，不能再投递了");
                //拒绝： 将队列中的消息删除 才能让队列中的其它消息继续消费  打日志  转人工
                //参数1：消息的标识
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                //false:没有投递过 本次是第一次投递
                System.out.println("没有投递过 本次是第一次投递");
                //参数1：消息的标识
                //参数2：是否批量应答
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                            false, true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }


    /**
     * 基于死信 接收消息 的监听器
     *
     * @param msg
     * @param message
     * @param channel
     */
    @RabbitListener(queues = DeadLetterMqConfig.queue_dead_2)
    public void receiverDeadLetterMessage(String msg, Message message, Channel channel) {

        try {
            System.out.println("接收到的消息：" + msg + ":时间是:" + new Date());

            //手动应答
            //参数1：消息的标识
            //参数2：是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //e.printStackTrace();
            //重新使用监听器获取队列中消息  重新接收一次
            //判断当前消息是否已经投递过了
            //                 如果已经投递过了 就证明上一次投递失败了 不能再投递一次
            //                 如果没有投递过、这是新消息  可以再投递一次
            //Boolean redelivered :
            //   是否投递过  true:已经投递过了本次第二次投递   false:没有投递过 本次是第一次投递
            if (message.getMessageProperties().isRedelivered()) {
                //true:已经投递过了本次第二次投递
                System.out.println("本次是第二次投递了，不能再投递了");
                //拒绝： 将队列中的消息删除 才能让队列中的其它消息继续消费  打日志  转人工
                //参数1：消息的标识
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                //false:没有投递过 本次是第一次投递
                System.out.println("没有投递过 本次是第一次投递");
                //参数1：消息的标识
                //参数2：是否批量应答
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                            false, true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }


    }


    //接收消息
    @RabbitListener(queues = "queue520")
    public void receiverMessage(String mgs, Message message, Channel channel) {

        try {
            System.out.println("接收到的消息：" + mgs);
            int i = 1 / 0;//  算术异常        RuntimeException   Exception
            //  FileNotFounded  IOException        Exception
            //手动应答
            //参数1：消息的标识
            //参数2：是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //e.printStackTrace();
            //重新使用监听器获取队列中消息  重新接收一次
            //判断当前消息是否已经投递过了
            //                 如果已经投递过了 就证明上一次投递失败了 不能再投递一次
            //                 如果没有投递过、这是新消息  可以再投递一次
            //Boolean redelivered :
            //   是否投递过  true:已经投递过了本次第二次投递   false:没有投递过 本次是第一次投递
            if (message.getMessageProperties().isRedelivered()) {
                //true:已经投递过了本次第二次投递
                System.out.println("本次是第二次投递了，不能再投递了");
                //拒绝： 将队列中的消息删除 才能让队列中的其它消息继续消费  打日志  转人工
                //参数1：消息的标识
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                //false:没有投递过 本次是第一次投递
                System.out.println("没有投递过 本次是第一次投递");
                //参数1：消息的标识
                //参数2：是否批量应答
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                            false, true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}
